package rothag.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.UUID;
import rothag.models.GameManager;
import rothag.models.MonumentJoueurInterface;
import rothag.models.PartieInterface;
import rothag.models.VilleInterface;
import rothag.enums.TypeDes;
import rothag.views.MainJFrame;
import rothag.listener.*;
import rothag.models.JoueurInterface;
import rothag.models.developpement.Developpement;

/**
 * Controller de l'application
 * @author Gaetan
 */
public class MainController {

    // Déclaration des attributs
    public MainJFrame view = null; // Vue
    private GameManager model = null; // Model

    /**
     * Constructeur
     * @param model Model à utiliser par le controller
     */
    public MainController(GameManager model) {
        this.model = model;

        // Instanciation de la vue
        view = new MainJFrame(this);
    }

    /**
     * Permet d'enregsitrer la partie courante
     * @throws Exception Fichier de sauvegarde invalide
     */
    public void enregistrerPartie() throws Exception {
        model.enregistrerPartie();
    }

    /**
     * Permet de récupérer la liste des parties sauvegardées
     * @return La liste des parties sauvegardées
     * @throws Exception Fichier de sauvegarde invalide
     */
    public ArrayList<PartieInterface> getPartiesSauvees() throws Exception {
        return model.getPartiesSauvees();
    }

    /**
     * Permet de charger une partie par son identifiant
     * @param identifiant Identifiant de la partie à charger
     * @throws Exception Fichier de sauvegarde non valide
     */
    public void chargerPartie(UUID identifiant) throws Exception {
        model.chargerPartie(identifiant);
    }

    /**
     * Permet de créer une nouvelle partie
     * @param listeNom Liste des joueurs de la partie
     */
    public void nouvellePartie(ArrayList<String> listeNom) {
        model.nouvellePartie(listeNom);
    }

    /**
     * Retourne la liste des dix meilleures parties solos
     * @return Liste de parties
     * @throws Exception Fichie de sauvegarde non valide
     */
    public ArrayList<PartieInterface> getTopTen() throws Exception {
        return model.getTopTen();
    }

    /**
     * Ajoute la partie courante dans le top ten
     * @return L'indice dans le classement, -1 si non classé
     * @throws Exception Fichie de sauvegarde non valide
     */
    public int ajoutScore() throws Exception {
        return model.ajouterScore();
    }

    /**
     * Permet de passer à l'étape suivante de la partie
     */
    public void etapeSuivante() {
        model.etapeSuivante();
    }

    /**
     * Permet au joueur courant de vendre une pierre contre trois ouvriers
     */
    public void vendrePierrePourOuvrier() {
        model.vendrePierrePourOuvrier();
    }

    /**
     * Permet d'ajouter un ouvrier à un monumement
     * @param monuementJoueur Monument à construire
     * @return Réussite ou échec
     */
    public boolean construireMonument(MonumentJoueurInterface monuementJoueur) {
        return model.construireMonument(monuementJoueur);
    }

    /**
     * Permet de construire un bateau
     * @return Réussite ou échec
     */
    public boolean construireBateau() {
        return model.construireBateau();
    }

    /**
     * Permet d'ajouter un ouvrier  à une ville
     * @param ville Ville à construire
     * @return Réussite ou échec
     */
    public boolean construireVille(VilleInterface ville) {
        return model.construireVille(ville);
    }

    /**
     * Retourne le nombre de villes réalisées par le joueur courant
     * @return Nombre de villes
     */
    public int getNbVilleJoueurCourant() {
        return model.getPartie().getJoueurCourant().getNbVilles();
    }

    /**
     * Retourne la liste des villes du joueur courant
     * @return Liste de villes
     */
    public ArrayList<VilleInterface> getListeVilleJoueurCourant() {
        return model.getPartie().getJoueurCourant().getListeVilles();
    }

    /**
     * Retourne la liste des monuments d'un joueur
     * @return Liste de monuments
     */
    public ArrayList<MonumentJoueurInterface> getListeMonumentJoueurCourant() {
        return model.getPartie().getJoueurCourant().getListeMonumentJoueur();
    }

    /**
     * Initialise la phase de lancement des dés
     * @return Le nombre de lancés possible
     */
    public int lancerDes() {
        model.lancerDes();
        return model.getPartie().getJoueurCourant().getNbLancesAurorises();
    }

    /**
     * Génère une liste de dés pour le joueur courant
     * @return Liste de dés
     */
    public ArrayList<TypeDes> genereDes() {
        return model.genereDes();
    }

    /**
     * Ajoute un dé dans la liste des dés sélectionnés du joueur
     * @param des Dé sélectionné par le joueur
     */
    public void selectionnerDes(TypeDes des) {
        model.selectionnerDes(des);
    }

    /**
     * Retire un dé de la liste des dés sélectionnés du joueur
     * @param des Dé à retirer
     * @return Si le dé a pu être rétiré
     */
    public boolean deselectionnerDes(TypeDes des) {
        return model.deselectionnerDes(des);
    }

    /**
     * Nourrit les villes du joueur après la sélection des dés
     * @param nbOuvriersSel Nombre d'ouvriers sélectionnés
     * @param nbNourritureSel Nombre d'ouvriers sélectionnés
     */
    public void nourrirVilles(int nbOuvriersSel, int nbNourritureSel) {
        model.nourrirVilles(nbOuvriersSel, nbNourritureSel);
    }

    /**
     * Applique les désatres au joueur courant
     */
    public void resoudreDesastres() {
        model.resoudreDesastres();
    }

    /**
     * Met à jour une ressource d'un joueur
     * @param ressource Ressource à mettre à jour
     * @param nbRessource Nombre de ressources à ajouter ou supprimer
     * @param log Vrai pour logger l'action dans les actions du joueur
     */
    public void majRessourceJoueurCourant(Class ressource, int nbRessource, boolean log) {
        model.majRessourceJoueurCourant(ressource, nbRessource, log);
    }

    /**
     * Retourne la liste des développements possibles de la partie
     * @return Liste de développements
     */
    public ArrayList<Developpement> getlisteDeveloppementPossible() {
        return model.getlisteDeveloppementPossible();
    }

    /**
     * Ajoute un développement à un joueur
     * @param dev Développement à ajouter
     * @param list Liste de ressources à utiliser
     * @param nbNourriture Nombre de nourriture à vendre
     * @return Résultat de l'achat
     */
    public boolean ajouterDeveloppementRealise(Developpement dev, ArrayList<Class> list, int nbNourriture) {
        return model.ajouterDeveloppementRealise(dev, list, nbNourriture);
    }

    /**
     * Récupère le nombre de resources à défausser
     * @return Nombre de ressource à défausser
     */
    public int defausse() {
        return model.defausse();
    }

    /**
     * Retourne le nombre de chaque ressource pour le joueur courant
     * @return Dictionnaire : Ressource/Nombre
     */
    public HashMap<Class, Integer> getNombreRessourceJoueurCourant() {
        return model.getNombreRessourceJoueurCourant();
    }

    /**
     * Retourne le classement des joueurs
     * @return Liste de joueurs classés par points
     */
    public ArrayList<JoueurInterface> getClassementJoueur() {
        return model.getClassementJoueur();
    }

    /**
     * Retourne le log des actions du tour pour le joueur courant
     * @return Liste d'actions sous forme de String
     */
    public ArrayList<String> getListeActionsJoueurCourant() {
        return model.getPartie().getListeActionsJoueurCourant();
    }

    /**
     * Permet d'ajouter un écouteur sur la partie
     * @param listener Ecouteur
     */
    public void addPartieListener(PartieListener listener) {
        model.addPartieListener(listener);
    }

    /**
     * Permet d'ajouter un écouteur sur le joueur courant
     * @param listener Ecouteur
     */
    public void addJoueurCourantListener(JoueurCourantListener listener) {
        model.addJoueurCourantListener(listener);
    }

    /**
     * Permet d'ajouter un écouteur sur les dés
     * @param listener Ecouteur
     */
    public void addDesListener(DesListener listener) {
        model.addDesListener(listener);
    }

    /**
     * Permet d'ajouter un écouteur sur les desastres
     * @param listener Ecouteur
     */
    public void addDesastreListener(DesastreListener listener) {
        model.addDesasteListener(listener);
    }

    /**
     * Affiche la vue
     */
    public void displayView() {
        view.setVisible(true);
    }
}
